package com.open4cn.simulator.device;

import cn.hutool.core.text.CharSequenceUtil;
import com.open4cn.simulator.core.device.DeviceParameters;
import com.open4cn.simulator.core.device.DeviceStatus;
import com.open4cn.simulator.core.device.IDevice;
import com.open4cn.simulator.core.device.IDeviceFactory;
import com.open4cn.simulator.core.exception.UnableToProcessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yinxiaopeng
 * @version 1.0.0
 * @company 致景科技
 * @department 飞梭BU/研发
 * @description 设备管理器
 * @Email yinxiaopeng@zj.tech
 * @date 2022-03-14 23:39
 */
public class DeviceManager {
    private static Logger logger = LoggerFactory.getLogger(DeviceManager.class);


    // k= 设备唯一标识
    private ConcurrentHashMap<String, IDevice> deviceContainer = new ConcurrentHashMap<>();


    /**
     * 加载设备
     *
     * @param deviceParameters
     * @return
     */
    public boolean load(DeviceParameters deviceParameters) {
        // 设备是否已经存在,存在则销毁重新加载
        String deviceId = deviceParameters.getId();
        if (CharSequenceUtil.isBlank(deviceId)) {
            return false;
        }
        if (exists(deviceId) && !stop(deviceId)) {
            throw new UnableToProcessException();
        }

        IDeviceFactory deviceFactory = DeviceFactoryRoute.route(deviceParameters.getBrand(), deviceParameters.getModel());
        IDevice device = deviceFactory.build(deviceParameters);
        if (null != device) {
            deviceContainer.put(deviceId, device);
            ConnectorManager.getInstance().put(deviceId, device.getConnector());
            return true;
        }
        return false;
    }


    public IDevice get(String deviceId) {
        if (null != deviceId && deviceId.length() != 0) {
            return deviceContainer.get(deviceId);
        }
        return null;
    }


    public boolean exists(String deviceId) {
        return null != get(deviceId);
    }

    public List<String> snapshot() {
        List<String> list = new ArrayList<>();
        deviceContainer.forEach((k, device) -> {
            String snapshot = snapshot(k);
            if (null != snapshot) {
                list.add(snapshot);
            }
        });
        return list;
    }

    public String snapshot(String deviceId) {
        if (!exists(deviceId)) {
            return null;
        }
        IDevice device = get(deviceId);
        StringBuilder builder = new StringBuilder();
        builder.append(device.getId())
                .append(":")
                .append(device.getDeviceInfo().getName())
                .append(":")
                .append(device.getDeviceStatus().getStatus().name())
                .append(":")
                .append(device.getConnector().getConnectStatus().getStatus().name());
        return builder.toString();
    }


    /**
     * 启动设备
     *
     * @param deviceId
     * @return
     */
    public boolean start(String deviceId) {
        if (!exists(deviceId)) {
            logger.error("{}设备不存在", deviceId);
            return false;
        }
        IDevice device = get(deviceId);
        if (null != device) {
            synchronized (device) {
                try {
                    return device.start();
                } catch (Exception e) {
                    logger.error("{}设备启动异常", deviceId, e);
                }
            }
        }
        return false;
    }


    /**
     * 暂停设备,不处理通讯
     *
     * @param deviceId
     * @return
     */
    public boolean suspend(String deviceId) {
        if (!exists(deviceId)) {
            logger.error("{}设备不存在", deviceId);
            return false;
        }
        IDevice device = get(deviceId);
        if (null != device) {
            synchronized (device) {
                try {
                    return device.suspend();
                } catch (Exception e) {
                    logger.error("{}设备暂停异常", deviceId, e);
                }
            }
        }
        return false;
    }


    /**
     * 关闭设备,断开连接
     *
     * @param deviceId
     * @return
     */
    public boolean stop(String deviceId) {
        if (!exists(deviceId)) {
            logger.error("{}设备不存在", deviceId);
            return true;
        }
        IDevice device = get(deviceId);
        if (null != device) {
            synchronized (device) {
                try {
                    if (device.stop() && device.destroy()) {
                        deviceContainer.remove(deviceId);
                        DeviceStatusManager.getInstance().remove(deviceId);
                        ConnectorManager.getInstance().remove(deviceId);
                        return true;
                    }
                } catch (Exception e) {
                    logger.error("{}设备关闭异常", deviceId, e);
                }
            }
        }
        return false;
    }


    /**
     * 清理已经关闭的设备,释放资源
     */
    public void clearAll() {
        deviceContainer.forEach((deviceId, device) -> {
            synchronized (device) {
                DeviceStatus deviceStatus = device.getDeviceStatus();
                try {
                    if (deviceStatus.isClosed() && device.destroy()) {
                        deviceContainer.remove(deviceId);
                        DeviceStatusManager.getInstance().remove(deviceId);
                        ConnectorManager.getInstance().remove(deviceId);
                    }
                } catch (Exception e) {
                    logger.error("{}设备清理异常", deviceId, e);
                }
            }
        });
    }

    /**
     * --------------------------------------------
     **/

    private DeviceManager() {
    }

    private static class HolderClass {
        private static final DeviceManager instance = new DeviceManager();
    }

    public static DeviceManager getInstance() {
        return HolderClass.instance;
    }
}
